package ar.edu.itba.pod.Legajo47342.communication;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashSet;
import java.util.Set;

import ar.edu.itba.pod.Legajo47342.Node;
import ar.edu.itba.pod.Legajo47342.communication.handlers.DisconnectHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.Handler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.NodeAgentLoadHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.NodeAgentLoadRequestHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.NodeMarketDataHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.NodeMarketDataRequestHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.ResourceRequestHandler;
import ar.edu.itba.pod.Legajo47342.communication.handlers.ResourceTransferMessageHandler;
import ar.edu.itba.pod.simul.communication.Message;
import ar.edu.itba.pod.simul.communication.MessageListener;

public class MessageListenerImpl implements MessageListener {

	private Node node;
	
	public MessageListenerImpl(Node node) throws RemoteException {
		super();
		this.node = node;
		
		UnicastRemoteObject.exportObject(this, 0);
	}
	
	@Override
	public boolean onMessageArrive(Message message) throws RemoteException {
		boolean isNew = isNew(message);
		
		if (isNew) {
			long timeStamp = System.currentTimeMillis();
			node.getLastMessageTime().put(message.getNodeId(), timeStamp);
			node.getMessages().put(timeStamp, message);
			processMessage(message);
		}
		
		return isNew;
	}

	@Override
	public Iterable<Message> getNewMessages(String remoteNodeId)
			throws RemoteException {
		
		long since = node.getLastTime(remoteNodeId);
		Set<Message> newMessages = new HashSet<Message>();
		
		for (long mTime : node.getMessages().keySet()) {
			if (mTime > since) {
				newMessages.add(node.getMessages().get(mTime));
			}
		}
		
		return newMessages;
	}
	
	private boolean isNew(Message message) {
		if(node.getMessages().containsValue(message)){
			return false;
		}else {
			return true;
		}
	}
	
	private void processMessage(Message message) {
		Handler h;
		
		switch (message.getType()) {
		case NODE_AGENTS_LOAD:
			h = new NodeAgentLoadHandler(node);
			h.handle(message);
			break;
		case NODE_AGENTS_LOAD_REQUEST:
			h = new NodeAgentLoadRequestHandler(node);
			h.handle(message);
			break;
		case DISCONNECT:
			h = new DisconnectHandler(node);
			h.handle(message);
			break;
		case NODE_MARKET_DATA:
			h = new NodeMarketDataHandler(node);
			h.handle(message);
			break;
		case NODE_MARKET_DATA_REQUEST:
			h = new NodeMarketDataRequestHandler(node);
			h.handle(message);
			break;
		case RESOURCE_TRANSFER:
			h = new ResourceTransferMessageHandler(node);
			h.handle(message);
			break;
		case RESOURCE_REQUEST:
			h = new ResourceRequestHandler(node);
			h.handle(message);
			break;
		case NEW_MESSAGE_REQUEST:
			//DEPRECATED
//			long lastTime = node.getLastMessageTime().get(message.getNodeId());
//			Set<Message> respMessages = new HashSet<Message>();
//			
//			for (long t : node.getMessages().keySet()) {
//				if (lastTime < t) {
//					respMessages.add(node.getMessages().get(t));
//				}
//			}
//			
//			NewMessageRequestPayload respPayload = 
//				(NewMessageRequestPayload) new NewMessageResponsePayloadImpl(respMessages);
//			Message resp = new Message(message.getNodeId(), 
//					System.currentTimeMillis(), MessageType.NEW_MESSAGE_RESPONSE, respPayload);
//			
//			try {
//				node.getManager().getGroupCommunication().send(resp, message.getNodeId());
//			} catch (RemoteException e) {
//				e.printStackTrace();
//			}
			break;
		case NEW_MESSAGE_RESPONSE:
			//DEPREACATEDDDDDDD
			break;
		
		default:
			break;
		}
		
	}

}
